package com.yunxin.admin.system.api.system;

import com.yunxin.admin.system.application.MenuApplicationService;
import com.yunxin.admin.system.application.MenuQueryService;
import com.yunxin.admin.system.application.command.AddMenuCommand;
import com.yunxin.admin.system.application.command.MenuCommand;
import com.yunxin.admin.system.application.command.UpdateMenuCommand;
import com.yunxin.admin.system.application.dto.MenuDTO;
import com.yunxin.admin.system.application.dto.MenuInfoDTO;
import com.yunxin.admin.system.application.dto.OptionDTO;
import com.yunxin.admin.system.application.dto.RouteDTO;
import com.yunxin.admin.system.infra.common.constant.SecurityConstants;
import com.yunxin.admin.system.infra.framework.resubmit.Resubmit;
import com.yunxin.admin.system.infra.framework.security.util.SecurityUtils;
import com.yunxin.admin.system.infra.framework.syslog.AutoLog;
import com.yunxin.common.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * 菜单控制器
 *
 * @author zero°
 * @since 2023-05-22
 */
@Tag(name = "04.菜单接口")
@RestController
@RequestMapping("/api/v1/menus")
@RequiredArgsConstructor
@Slf4j
public class SysMenuController {

    private final MenuApplicationService menuService;

    private final MenuQueryService menuQueryService;



    @Operation(summary = "菜单列表", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
    @GetMapping
    public Result<List<MenuDTO>> listMenus(@ParameterObject MenuCommand request) {
        List<MenuDTO> list = menuQueryService.listMenus(request.getKeywords());
        return Result.success(list);
    }

    @Operation(summary = "菜单下拉列表", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
    @GetMapping("/options")
    public Result<List<OptionDTO<Long>>> listMenuOptions() {
        List<OptionDTO<Long>> menus = menuQueryService.listMenuOptions();
        return Result.success(menus);
    }

    @Operation(summary = "路由列表", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
    @GetMapping("/routes")
    public Result<List<RouteDTO>> listRoutes() {
        List<RouteDTO> routeList = menuQueryService.listRoutes();
        if (SecurityUtils.X.isRoot()){
            List<RouteDTO> routeList2 = new ArrayList<>(routeList);
            for (int i=0;i<routeList2.size();i++) {
                RouteDTO routeDTO = routeList2.get(i);
                if (routeDTO.getPath().equals("/config")){
                    routeList2.remove(i);
                    break;
                }
            }
            return Result.success(routeList2);
        }
        return Result.success(routeList);
    }

    @Operation(summary = "菜单表单数据", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
    @GetMapping("/{id}/form")
    public Result<MenuInfoDTO> getMenuForm(@Parameter(description = "菜单ID") @PathVariable Long id) {
        MenuInfoDTO menuInfoDTO = menuQueryService.getMenuById(id);
        return Result.success(menuInfoDTO);
    }

    @Operation(summary = "新增菜单", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
    @PostMapping
    @PreAuthorize("@ss.hasPerm('sys:menu:add')")
    @Resubmit
    @AutoLog(value = "新增菜单")
    @CacheEvict(cacheNames = "system", key = "'routes'")
    public Result<Boolean> addMenu(@RequestBody AddMenuCommand command) {
        boolean result = menuService.saveMenu(command);
        return Result.judge(result);
    }

    @Operation(summary = "修改菜单", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
    @PutMapping(value = "/{id}")
    @PreAuthorize("@ss.hasPerm('sys:menu:edit')")
    @CacheEvict(cacheNames = "system", key = "'routes'")
    public Result<Boolean> updateMenu(@RequestBody UpdateMenuCommand command) {
        boolean result = menuService.updateMenu(command);
        return Result.judge(result);
    }


    @Operation(summary = "删除菜单", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
    @DeleteMapping("/{id}")
    @PreAuthorize("@ss.hasPerm('sys:menu:delete')")
    @CacheEvict(cacheNames = "system", key = "'routes'")
    @AutoLog(value = "删除菜单")
    public Result<Boolean> deleteMenu(@Parameter(description = "菜单ID，多个以英文(,)分割") @PathVariable("id") Long id) {
        boolean result = menuService.deleteMenu(id);
        return Result.judge(result);
    }

    @Operation(summary = "修改菜单显示状态", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
    @PatchMapping("/{menuId}")
    @AutoLog(value = "修改菜单显示状态")
    public Result<Boolean> updateMenuVisible(@Parameter(description = "菜单ID") @PathVariable Long menuId,
            @Parameter(description = "显示状态(1:显示;0:隐藏)") Integer visible) {
        boolean result = menuService.updateMenuVisible(menuId, visible);
        return Result.judge(result);
    }






}

